El mercado de los videojuegos, un área de interés común para los integrantes del grupo, ha crecido muchísimo en los últimos años. Esto se aprecia tanto al observar la cantidad de personas aficionadas a este hobby como la variedad de juegos publicados cada año, además de los avances en gráficos y otras tecnologías que se han logrado con el tiempo.
Otro detalle relevante es el aporte que hoy en día ofrecen plataformas de gestión y venta de videojuegos como Steam e Itch.io, las que permiten que desarrolladores independientes o grupos pequeños de estos puedan ser visibilizados y publicar sus juegos sin necesitar de grandes inversiones, volviendo alcanzable ingresar y/o dedicarse al área.
El dataset escogido para el proyecto corresponde a información respecto a videojuegos recopilada de la plataforma Steam. Fue obtenido originalmente de Kaggle.
El autor de este dataset comenta que los datos fueron extraídos utilizando una plataforma externa, SteamSpy, la cual tiene una API que recopila al detalle varias estadísticas de Steam. Este dataset contiene estadísticas hasta el mes de mayo del 2019.
Por un lado, como a nivel personal y grupal se ha observado la evolución de los videojuegos en la época contemporánea, resulta atractiva la idea de encontrar (más allá de la impresión personal que se pueda tener) evidencia tangible de tendencias que se han dado respecto a los juegos con el paso de los años.
Observando lo vigente que resulta el área, y aprovechando la oportunidad del proyecto de este curso, se aspirará también a identificar patrones que puedan resultar provechosos al momento de elegir ciertas características que tendrá un juego, tal que incluirlos pueda significar un mayor interés por parte del público.
La descarga desde Kaggle se compone de 6 archivos csv, donde la información más importante respecto a los juegos se encuentra en steam.csv. Este será el archivo utilizado para realizar la exploración que se describe en este documento.
Nota: Esta parte del informe difiere con lo entregado para el hito 1 para resumir mejor la información. En esta instancia realizamos una serie de cambios: definimos preguntas finales más concisas para llegar a resultados más tangibles, omitimos las exploraciones que no colaboran a responder las preguntas, eliminamos varios bloques de código.
A continuación se describen los atributos de la tabla principal, steam.csv.
Para mayor facilidad en la interpretación de los precios, fue necesario hacer una conversión a la moneda local (CLP). No confundir con los precios reales en la tienda de Chile, los cuales pueden no ser iguales a los que se muestren en este análisis.
Adicionalmente, existen otros atributos que, de forma similar a las compañías desarrolladoras y distribuidoras, se encontraban separadas con punto y coma, pero al ser una cantidad de opciones más reducida se decidió pre-procesar los datos y transformar cada uno de los atributos en columnas adicionales, indicando si incluyen o no cierta característica, de entre todas las opciones posibles. Los atributos alterados fueron los siguientes:
El dataset original no contiene elementos vacíos (NaN) y posee 27075 observaciones que corresponden a los juegos presentes en la plataforma steam.
if (!require('tidyverse')) install.packages('tidyverse'); library('tidyverse')
if (!require('splitstackshape')) install.packages('splitstackshape'); library('splitstackshape')
steam <- read.csv("data/steam.csv", encoding = "UTF-8", as.is = F)
platforms <- str_split(steam$platforms, ";")
categories <- str_split(steam$categories, ";")
genres <- str_split(steam$genres, ";")
platforms <- unlist(platforms)
categories <- unlist(categories)
genres <- unlist(genres)
platforms <- unique(platforms)
categories <- unique(categories)
genres <- unique(genres)
steam <- cSplit(steam, "platforms", sep=";")
steam <- cSplit(steam, "categories", sep=";")
steam <- cSplit(steam, "genres", sep=";")
for (i in platforms){
steam <- steam %>%
mutate(!!i := if_any(starts_with("platforms"), ~ ifelse(.x == i,1,0)))
}
for (i in categories){
steam <- steam %>%
mutate(!!i := if_any(starts_with("categories"), ~ ifelse(.x == i,1,0)))
}
for (i in genres){
steam <- steam %>%
mutate(!!i := if_any(starts_with("genres"), ~ ifelse(.x == i,1,0)))
}
GBP_TO_CLP_RATE <- 1085
steam$price <- round(steam$price * GBP_TO_CLP_RATE)
steam <- steam %>%
mutate_at(c(53:113), ~ifelse(is.na(.x)==T | .x ==F,0,1))
Medidas de tendencia central, dispersión y rango de variables númericas.
steam %>%
select(achievements,positive_ratings,negative_ratings,average_playtime,median_playtime,
price) %>%
summary()
## achievements positive_ratings negative_ratings average_playtime
## Min. : 0.00 Min. : 0 Min. : 0 Min. : 0.0
## 1st Qu.: 0.00 1st Qu.: 6 1st Qu.: 2 1st Qu.: 0.0
## Median : 7.00 Median : 24 Median : 9 Median : 0.0
## Mean : 45.25 Mean : 1001 Mean : 211 Mean : 149.8
## 3rd Qu.: 23.00 3rd Qu.: 126 3rd Qu.: 42 3rd Qu.: 0.0
## Max. :9821.00 Max. :2644404 Max. :487076 Max. :190625.0
## median_playtime price
## Min. : 0.0 Min. : 0
## 1st Qu.: 0.0 1st Qu.: 1834
## Median : 0.0 Median : 4329
## Mean : 146.1 Mean : 6595
## 3rd Qu.: 0.0 3rd Qu.: 7801
## Max. :190625.0 Max. :457859
english no resultará muy útil pues casi todos los juegos están en inglés (lo que es esperable al ser Steam una plataforma originalmente en este idioma).achievements, aunque existen algunos que parecieran enfocarse en lo contrario y presentan un número absurdamente alto de logros.positive_ratings y negative_ratings, de otra forma los juegos “más populares” posiblemente terminarían opacando a los demás.average_playtime como median_playtime tienen mediana cero.A continuación se muestran los valores tabulados correspondientes a los 10 juegos con mayor cantidad de positive_ratings, de negative_ratings y también de una variable auxiliar rating_neto, que corresponde a la diferencia entre los positive_ratings y negative_ratings.
## name positive_ratings
## 1: Counter-Strike: Global Offensive 2644404
## 2: Dota 2 863507
## 3: Team Fortress 2 515879
## 4: PLAYERUNKNOWN'S BATTLEGROUNDS 496184
## 5: Garry's Mod 363721
## 6: Grand Theft Auto V 329061
## 7: PAYDAY 2 308657
## 8: Unturned 292574
## 9: Terraria 255600
## 10: Left 4 Dead 2 251789
## name negative_ratings
## 1: PLAYERUNKNOWN'S BATTLEGROUNDS 487076
## 2: Counter-Strike: Global Offensive 402313
## 3: Dota 2 142079
## 4: Grand Theft Auto V 139308
## 5: Z1 Battle Royale 91664
## 6: DayZ 77169
## 7: ARK: Survival Evolved 66603
## 8: Tom Clancy's Rainbow Six® Siege 59620
## 9: PAYDAY 2 56523
## 10: No Man's Sky 56488
## name rating_neto
## 1: Counter-Strike: Global Offensive 2242091
## 2: Dota 2 721428
## 3: Team Fortress 2 481843
## 4: Garry's Mod 347288
## 5: Unturned 261092
## 6: PAYDAY 2 252134
## 7: Terraria 247803
## 8: Left 4 Dead 2 243371
## 9: The Elder Scrolls V: Skyrim 222352
## 10: Rocket League® 220745
Se puede observar que la mayoría del top 10 de juegos con mayor cantidad de ratings positivos también se encuentra en el top 10 de juegos con mayor cantidad de ratings negativos, lo cual parece indicar que los juegos populares tienden a tener una gran cantidad de calificaciones positivas y negativas al mismo tiempo.
A continuación se muestran los 10 juegos con mayor average_playtine y median_playtime.
## name average_playtime
## 1: The Abbey of Crime Extensum 190625
## 2: The Banner Saga: Factions 95245
## 3: The Secret of Tremendous Corporation 95242
## 4: PRICE 63481
## 5: Boundless 55204
## 6: Shroud of the Avatar: Forsaken Virtues 54618
## 7: X-Plane 11 44169
## 8: <U+61D2><U+4EBA><U+4FEE><U+4ED9><U+4F20> 43632
## 9: Fantasy Grounds 43074
## 10: Screeps 38805
## name median_playtime
## 1: The Abbey of Crime Extensum 190625
## 2: The Banner Saga: Factions 190489
## 3: The Secret of Tremendous Corporation 190445
## 4: Fantasy Grounds 86148
## 5: <U+61D2><U+4EBA><U+4FEE><U+4ED9><U+4F20> 71857
## 6: PRICE 63490
## 7: Boundless 55204
## 8: Shroud of the Avatar: Forsaken Virtues 54618
## 9: X-Plane 11 44169
## 10: Screeps 38805
Los resultados obtenidos abren muchas dudas de la fiabilidad y validez de estas variables, ya que luego de realizar un análisis cualitativo de varios de estos juegos se observó que no es esperable que posean tantas horas de juego. Dado lo anterior, se decidió continuar con cautela respecto a estas variables, y seguir investigando si pudiesen contener errores o outliers muy extremos.
Un ejemplo se puede observar en el juego The Abbey of Crime Extensum, que en el dataset reporta 190625 minutos (unas 3177 horas) y en la plataforma How Long to Beat reporta, en el caso más extremo, apenas 5 horas.
A continuación se muestran los 10 juegos con mayor precio en Steam , junto con un gráfico que representa la densidad de precios entre los datos.
## name price
## 1: ADR-Labelling Game 457859
## 2: GameMaker Studio 2 UWP 329829
## 3: Houdini Indie 227839
## 4: 3DF Zephyr Lite Steam Edition 168164
## 5: Tactics: Bludgeons Blessing 168164
## 6: Silhouette 168164
## 7: GameMaker Studio 2 Mobile 168164
## 8: CrisisActionVR 168164
## 9: Tactics 2: War 168164
## 10: Bible Test 168164
Muchos de los juegos de mayor precio corresponden a géneros de herramientas de software (Animation & Modeling, Design & Ilustration). Además, existe una gran cantidad de juegos económicos, y la gran mayoría se encuentra en el rango de precios menos que 10000 CLP.
Nota: e+05 = 100000.
Vale la pena destacar que los datos consideran desde el año 1997 hasta 2019. Hay muy pocos juegos que tuvieron su lanzamiento antes del año 2006, así que se observó con mayor atención los años 2006 y posteriores.
Como los datos fueron recolectados en 2019, es esperable que no se tenga información completa respecto al último año. A continuación se observa que los datos solo llegan hasta el mes 5 del 2019, es decir Mayo.
# Confirmando el juego más reciente en la tabla (mes):
steam %>%
filter(year==2019) %>% select(month) %>% arrange(-month) %>% head(1)
## month
## 1: 5
En este apartado se puede ver la distribución de las plataformas donde los juegos de Steam están disponibles.
Solo hay 3 plataformas en PC, siendo liderado por Windows.
## variable value
## 1 windows_excl 18398
## 2 mac_excl 3
## 3 linux_excl 1
Otra situación que se da es que prácticamente nadie crea contenido exclusivo para Mac o Linux. Lo común es que los desarrolladores liberen sus juegos en Windows, y en ocasiones también deciden agregar otras plataformas.
Existen un total de 6 categorías según el sistema inglés.
unique(steam$required_age)
## [1] 0 18 16 12 7 3
La mayor parte de los juegos no indican un rating (clasificación 0):
## required_age n
## 1: 0 26479
## 2: 3 11
## 3: 7 12
## 4: 12 73
## 5: 16 192
## 6: 18 308
Lo anterior puede deberse a que solo es importante etiquetarlos cuando se trata de juegos para mayores de edad, y que por eso la tendencia sea a aumentar la cantidad con el rating de edad. Otra situación que podría estar también pasando es que el rating está pendiente de evaluación del organismo PEGI UK, distinto al sistema ESRB que se usa en américa.
Se identificaron un total de 29 géneros distintos:
## variable value
## 1 Indie 19421
## 2 Action 11903
## 3 Casual 10210
## 4 Adventure 10032
## 5 Strategy 5247
## 6 Simulation 5194
## 7 RPG 4311
## 8 Early Access 2954
## 9 Free to Play 1704
## 10 Sports 1322
## 11 Racing 1024
## 12 Violent 843
## 13 Massively Multiplayer 723
## 14 Gore 537
## 15 Nudity 266
## 16 Sexual Content 245
## 17 Utilities 146
## 18 Design & Illustration 87
## 19 Animation & Modeling 79
## 20 Steam Turn Notifications 63
## 21 Education 51
## 22 Video Production 38
## 23 Software Training 31
## 24 Audio Production 29
## 25 Web Publishing 28
## 26 Game Development 17
## 27 Photo Editing 12
## 28 Accounting 6
## 29 Documentary 1
Algunos de los anteriores corresponden a géneros de software y no necesariamente de juegos. Sin embargo, los más frecuentes se corresponden con géneros más bien conocidos de videojuegos, mientras que los géneros de softwares de utilidad presentan baja frecuencia.
Para distinguir de mejor forma los grupos se prefirió convertir el valor asociado (originalmente un intervalo) a un valor numérico, promediando ambos límites de dicho intervalo. Los intervalos se distinguen bajo el atributo dueños promedio.
owners <- str_split(steam$owners, "-")
owners <- unlist(owners)
owners <- unique(owners)
steam <- cSplit(steam, "owners", sep="-")
steam <- steam %>%
mutate(duenos_promedio = (owners_1 + owners_2)/2)
## name duenos_promedio
## 1: Dota 2 1.5e+08
## 2: Counter-Strike: Global Offensive 7.5e+07
## 3: PLAYERUNKNOWN'S BATTLEGROUNDS 7.5e+07
## 4: Team Fortress 2 3.5e+07
## 5: Warframe 3.5e+07
## 6: Unturned 3.5e+07
## 7: Counter-Strike 1.5e+07
## 8: Counter-Strike: Condition Zero 1.5e+07
## 9: Half-Life 2 1.5e+07
## 10: Counter-Strike: Source 1.5e+07
Nota: e+07 = 10 millones.
La tabla anterior muestra los juegos con la mayor cantidad de dueños en Steam. Por otra parte, para conocer cuántos juegos hay por rango de dueños (formato nativo de los datos del csv) se realizó lo siguiente:
En este apartado se realizan transformaciones logarítmicas a algunas variables para suavizar las observaciones y distribuciones.
## # A tibble: 10 x 2
## variable media_duenos_genero
## <fct> <dbl>
## 1 Massively Multiplayer 617220.
## 2 Free to Play 592667.
## 3 Action 198411.
## 4 RPG 161648.
## 5 Animation & Modeling 150759.
## 6 Strategy 146379.
## 7 Design & Illustration 126897.
## 8 Adventure 109823.
## 9 Utilities 102158.
## 10 Simulation 101261.
Existen outliers entre los juegos “Free to Play” cuyo precio es mayor a cero. Además podemos observar que la mayoría de juegos “Massive Multiplayer” son gratuitos o tienen precios más bajos que los otros géneros más comunes, de los cuales los juegos del género “RPG” tienden a tener mayor precio.
En el grafico se puede ver la evolucion de los géneros de juegos más presentes en Steam. Se puede concluir que desde el 2013, estos 5 géneros han subido su cantidad de juegos consistentemente, siendo Indie el que más ha aumentado su oferta de juegos y siendo los de estrategia los que menos lo han hecho. También se puede ver que todos disminuyen el 2019, pero como ya se explicó anteriormente esto sucede debido a que la informacion solo llega a Mayo de ese año.
El gráfico muestra una tendencia a la baja, que se puede deber a que el gráfico representa los años de lanzamiento de los juegos, en vez de una evolución de usuarios por año. Esto explica por qué juegos antiguos han sido adquiridos por una mayor cantidad de usuarios que los más recientes. Además, el spike en el año 2013 se puede deber a que corresponde el año de salida de Dota 2, el juego con mayor cantidad de usuarios y que pertenece a los géneros “Action”, “Strategy” y “Free to Play”.
if (!require('corrplot')) install.packages('corrplot'); library('corrplot')
steam <- steam %>%
mutate(rating_neto = positive_ratings - negative_ratings) %>%
mutate(rating_perc = positive_ratings/(positive_ratings + negative_ratings))
steam %>%
select(positive_ratings,negative_ratings,rating_neto,rating_perc,average_playtime,median_playtime,price,duenos_promedio,achievements) %>%
cor() %>%
corrplot()
Con la información anterior se puede notar que la variable price no está fuertemente correlacionada con ninguna variable. Por otro lado, un aspecto interesante es el hecho que la cantidad de dueños promedio está fuertemente correlacionada positivamente con las variables de ratings. Se puede concluir que la cantidad de ratings (ya sean positivos o negativos) podrían estar reflejando la popularidad de los juegos. Además, la cantidad de logros no parece ser relevante. Agregamos también una variable que represente la fracción de ratings positivos, la cual nos podría servir más adelante a pesar de no presentar correlaciones relevantes.
La exploración actual muestra un punto de partida para analizar este problema.
Tareas como medir el éxito de un juego y determinar a priori si un juego será o no exitoso podrían ser respondidas al utilizar herramientas de clasificación/regresión.
¿Qué factores afectan más en producir altos tiempos de juego? (cantidad de achievements o juegos multiplayer por ejemplo)
¿Cuáles son los géneros de juegos indie que producen más engagement? (mayores playtimes y más owners)
5.¿Cómo abordar problemas con los datos originales?
El dataset original presenta varios detalles que entorpecen el análisis, tales como:
Por lo que podría ser prudente aplicar filtros o transformaciones adecuadas al dataset antes de utilizarlo en tareas más complejas como lo son la clasificación y clustering.
Como se mencionó anteriormente, se redujo el análisis exploratorio para mostrar unicamente información relevante y mejor presentada. También replantearemos nuestras interrogantes:
Es necesario procesar el grupo de datos para que sea útil no solo al observar sus atributos, también para poder contestar las preguntas que plantearemos y llegar a conclusiones satisfactorias.
La exploración actual muestra un punto de partida para analizar este problema. Esta pregunta puede ser respondida con un análisis superficial.
¿Qué factores determinar que un juego es exitoso y/o popular entre los jugadores?
¿Cómo podemos predecir si un juego va a ser exitoso?
Tareas como medir el éxito de un juego y determinar a priori si un juego será o no exitoso podrían ser respondidas al utilizar herramientas de clustering/clasificación.
Primero podemos eliminar directamente los atributos que no nos serviran más.
[ english ; required_age ; steamspy_tags ; achievements ]
Eliminaremos todas las columnas referentes a la fecha de salida de un juego, excepto year.
Eliminaremos las columnas positive_ratings y negative_ratings para quedarnos solo con rating_neto y rating_perc, asi tenemos la misma información pero de otra manera que podría ser más útil.
Luego; eliminaremos Plataforms por poseer una unica clase dominante, eliminaremos categories ya que se trata más de un aspecto técnico de cada software que no nos dice mucho, y eliminaremos cada variable dummy derivada de éstas. Además eliminaremos los atributos de playtime, por demostrar ser poco fiables.
Por último, para genres eliminamos todas las variables dummy correspondientes a generos con menos frecuencia que Utilities (incluyendolo), ya que presentan muy pocas entradas y tampoco nos interesan software de utilidad que no son juegos.
Está de más decir que también eliminaremos las columnas que fueron usadas como paso intermedio para arreglar el dataset, pues no fueron hechas para ser tomadas en cuenta.
steam_nuevo <- steam %>%
subset(select = -c(3,4,7:12,13,15:83,90,91,101:105,107:113,115:117)) %>%
relocate(c(22:25), .after = 5)
steam_nuevo <- steam_nuevo %>%
mutate(nGenres = rowSums(select(steam_nuevo,c(10:25)))) %>%
filter(nGenres > 0) %>%
select(-nGenres)
Atributos básicos del nuevo dataset:
## [1] "appid" "name" "developer" "publisher"
## [5] "price" "year" "duenos_promedio" "rating_neto"
## [9] "rating_perc"
Variables dummy para cada género de videojuego:
## [1] "Action" "Free to Play" "Strategy"
## [4] "Adventure" "Indie" "RPG"
## [7] "Casual" "Simulation" "Racing"
## [10] "Violent" "Massively Multiplayer" "Nudity"
## [13] "Sports" "Early Access" "Gore"
## [16] "Sexual Content"